#include "bsp_i2c.h"
#include "cbb_init.h"
#include "at32f403a_407.h"

void bsp_i2c_init(void){

    crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

    gpio_init_type gpio_init_struct;
  
    /* configure the SCL SDA pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7;
    gpio_init(GPIOB, &gpio_init_struct);
  
    i2c_init(I2C1, I2C_FSMODE_DUTY_2_1, 100000);
    i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, 0x0);
    i2c_ack_enable(I2C1, TRUE);
    i2c_clock_stretch_enable(I2C1, TRUE);
    i2c_general_call_enable(I2C1, FALSE);
  
    i2c_enable(I2C1, TRUE);
}
INIT_PORT_BSP(bsp_i2c_init);

uint8_t i2c1_transmit(uint8_t u8Addr, uint8_t *pu8Data, uint32_t u32Length, uint32_t u32Timeout) {
    
    // 超时时间
    uint32_t timeout = 0;

    // 等待总线空闲
    timeout = u32Timeout;
    while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) == 1 && timeout--);
    if(timeout == 0) {
        i2c_stop_generate(I2C1);
        return 1;
    }

    // 生成START信号
    i2c_start_generate(I2C1);

    // 等待起始信号发送完成
    timeout = u32Timeout;
    while(i2c_flag_get(I2C1, I2C_STARTF_FLAG) == 0 && timeout--);
    if(timeout == 0) {
        i2c_stop_generate(I2C1);
        return 1;
    }

    // 发送设备地址（写模式）
    i2c_7bit_address_send(I2C1, u8Addr, I2C_DIRECTION_TRANSMIT);
    
    // 等待地址发送完成
    timeout = u32Timeout;
    while(i2c_flag_get(I2C1, I2C_ADDR7F_FLAG) == 0 && timeout--);
    if(timeout == 0) {
        i2c_stop_generate(I2C1);
        return 1;
    }

    // 清标志位
    I2C1->sts1;
    I2C1->sts2;

    // 发送数据
    for(uint16_t i = 0; i < u32Length; i++) {

        // 等待移位寄存器为空
        timeout = u32Timeout;
        while(i2c_flag_get(I2C1, I2C_TDBE_FLAG) == 0 && timeout--);
        if(timeout == 0) {
            i2c_stop_generate(I2C1);
            return 1;
        }

        // 发送数据
        i2c_data_send(I2C1, pu8Data[i]);

        // 等待数据发送完成
        timeout = u32Timeout;
        while(i2c_flag_get(I2C1, I2C_TDC_FLAG) == 0 && timeout--);
        if(timeout == 0) {
            i2c_stop_generate(I2C1);
            return 1;
        }
    }

    // 生成STOP信号
    i2c_stop_generate(I2C1);
    return 0;
}


uint8_t i2c1_receive(uint8_t u8Addr, uint8_t *pu8Data, uint32_t u32Length, uint32_t u32Timeout) {

    // 超时时间
    uint32_t timeout = 0;

    // 等待总线空闲
    timeout = u32Timeout;
    while(i2c_flag_get(I2C1, I2C_BUSYF_FLAG) && timeout--);
    if(timeout == 0) {
        i2c_stop_generate(I2C1);
        return 1;
    }

    // 生成START信号
    i2c_ack_enable(I2C1, TRUE);
    i2c_start_generate(I2C1);

    // 等待起始信号发送完成
    timeout = u32Timeout;
    while(i2c_flag_get(I2C1, I2C_STARTF_FLAG) == 0 && timeout--);
    if(timeout == 0) {
        i2c_stop_generate(I2C1);
        return 1;
    }

    // 发送设备地址（读模式）
    i2c_7bit_address_send(I2C1, u8Addr, I2C_DIRECTION_RECEIVE);
    
    // 等待地址发送完成
    timeout = u32Timeout;
    while(i2c_flag_get(I2C1, I2C_ADDR7F_FLAG) == 0 && timeout--);
    if(timeout == 0) {
        i2c_stop_generate(I2C1);
        return 1;
    }

    // 清标志位
    I2C1->sts1;
    I2C1->sts2;

    // 读取数据
    for(uint16_t i = 0; i < u32Length; i++) {

        if(i == u32Length-1) {
            i2c_ack_enable(I2C1, FALSE);  // 最后一个字节发NACK
            i2c_stop_generate(I2C1);                // 提前生成STOP
        }
        
        // 等待数据接收完成
        timeout = u32Timeout;
        while(i2c_flag_get(I2C1, I2C_RDBF_FLAG) == 0 && timeout--);
        if(timeout == 0) {
            i2c_stop_generate(I2C1);
            return 1;
        }

        // 读取数据
        pu8Data[i] = i2c_data_receive(I2C1);

    }

    // 生成STOP信号
    i2c_stop_generate(I2C1);
    return 0;
}
